/**
 * Copyright [2019] [LiBo/Alex of copyright liboware@gmail.com ]
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.classcode.proxy;

import com.hyts.classcode.classload.load.LocalClassLoader;
import sun.misc.ProxyGenerator;

import java.io.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.stream.Stream;

/**
 * @project-name:coffice-toolbox
 * @package-name:com.hyts.classcode.proxy
 * @author:LiBo/Alex
 * @create-date:2019-10-22 13:20
 * @copyright:libo-alex4java
 * @email:liboware@gmail.com
 * @description:
 */

public class ProxyToolProvider {


    public static byte[] generateProxyObject(String proxyName,Class<?>... clazz){
        if(clazz != null && clazz.length > 0) {
            return ProxyGenerator.generateProxyClass(proxyName, clazz);
        }
        return new byte[0];
    }

    public static byte[] generateProxyObjectPublic(String proxyName,Class<?>... clazz){
        if(clazz != null && clazz.length > 0) {
            return ProxyGenerator.generateProxyClass(proxyName, clazz,Modifier.PUBLIC);
        }
        return new byte[0];
    }

    public static byte[] generateProxyObjectProtected(String proxyName,Class<?>... clazz){
        if(clazz != null && clazz.length > 0) {
            return ProxyGenerator.generateProxyClass(proxyName, clazz,Modifier.PROTECTED);
        }
        return new byte[0];
    }

    public static byte[] generateProxyObjectFinal(String proxyName,Class<?>... clazz){
        if(clazz != null && clazz.length > 0) {
            return ProxyGenerator.generateProxyClass(proxyName, clazz,Modifier.FINAL | Modifier.PUBLIC);
        }
        return new byte[0];
    }


    public static Class generateProxyClassObj(byte[] classFile,ClassLoader classLoader,String proxyClassName){
        return defineClass0(classLoader,proxyClassName,classFile,0,classFile.length);
    }

    public static Class generateProxyClassObj(byte[] classFile,String proxyClassName){
        return defineClass0(ProxyToolProvider.class.getClassLoader(),proxyClassName,classFile,0,classFile.length);
    }

    private static native Class<?> defineClass0(ClassLoader loader, String name,
                                                byte[] b, int off, int len);



    public static void main(String[] args){
        /*Class clazz = generateProxyClassObj(ProxyToolProvider.generateProxyObject("com.hyts.classcode.proxy.TestAdImpl",Ad.class)
                ,Ad.class.getClassLoader(),"com.hyts.classcode.proxy.TestAdImpl");

        try {
            ((Ad)clazz.getConstructor(InvocationHandler.class).newInstance(new AdInvocationHandler())).add();
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }*/
        try {
            Class clazz  = new LocalClassLoader(ProxyToolProvider.class.getClassLoader()).getClass(
                    "com.hyts.classcode.proxy.TestAdImpl",ProxyToolProvider.generateProxyObject("com.hyts.classcode.proxy.TestAdImpl",Ad.class));

            ((Ad)clazz.getConstructor(InvocationHandler.class).newInstance(new AdInvocationHandler())).add();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException | NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        String path  = "/Users/alex/Documents/我的代码/coffice-toolbox/coffice-toolbox-utils/coffice-toolbox-classcode/build/compile/TestAdImpl.class";
        /*byte[] code = ProxyToolProvider.generateProxyObject("com.hyts.classcode.proxy.TestAdImpl",Ad.class);
        System.out.println(code.length);
        try (
                FileOutputStream outputStream = new FileOutputStream(path);
                ByteArrayInputStream inputStream =  new ByteArrayInputStream(code);
                ){
            int index = 0;
            while((index = inputStream.read())!= -1){
                outputStream.write(index);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {

        }*/
    }

}
